package com.game.raceroom.player	
{
	import com.util.DEF;
	public class ConflictChecker
	{
		private var car:Player;
		private var mapInfo:MapInfo;
		private static var i16:int=16;
		private static var i0:int = 0;
		private static var i1 :int= 1;
		private static var i_1 :int= -1;
		private static var d1d5 :Number= 1.5;
		public function ConflictChecker(actorContrl:Player)
		{
			this.car=actorContrl;
            this.mapInfo=actorContrl.mapInfo;
            half=car.carInfo.confRadius/2;
		}
        private var hasConflict:Boolean=false;
        private var x_flg:int;
        private var y_flg:int;
        private var xx:Number;
        private var yy:Number;
        private var divx:Number;
        private var divy:Number;
        private var abs_x_off:Number;
        private var abs_y_off:Number;
        private var hadCrash:Boolean;
 		public function checkConflict(x_off:Number,y_off:Number):void{
 		   if(x_off==i0 && y_off==i0)return;
 		   //trace("offf   "+x_off+"  "+y_off);
 	       if(x_off<i0){
 	       		x_dir=DEF.DIRECTION_LEFT;
 	       		x_flg=i_1;
 	       }
	       else {
	       		x_dir=DEF.DIRECTION_RIGHT;
	       		x_flg=i1;
	       }
	       		
	       if(y_off<i0){
	       		y_dir=DEF.DIRECTION_UP;
	       		y_flg=i_1;
	       }
	       else {
	       		y_dir=DEF.DIRECTION_DOWN;
	       		y_flg=i1;
	       }
	       //x方向位移量大
	       divx=i0;
	       divy=i0;
	       abs_x_off=Math.abs(x_off);
	       abs_y_off=Math.abs(y_off); 
	      // moveLogic(abs_x_off,abs_y_off);
 		   if(abs_x_off>abs_y_off){
 		   	   divx=abs_y_off/abs_x_off;
 		   	   if(abs_x_off>i16){   	   
 	   	   	  	 	while(abs_x_off>i0){
 	   	   	  	 		if(abs_x_off>i16){
 	   	   	  	 			xx=i16;
 	   	   	  	 		}else{
 	   	   	  	 			xx=abs_x_off;
 	   	   	  	 		}
 	   	   	  	 		abs_x_off-=xx;
 	   	   	  	 		yy=xx*divx;
 	   	   	  	 		//abs_y_off-=yy;
 	   	   	  	 		hadCrash=moveLogic(xx,yy);	 
 	   	   	  	 		if(hadCrash)return;  	   	  	 		 
 	   	   	  	 	}
 		   	   }else{
 		   	   	  moveLogic(Math.abs(x_off),Math.abs(y_off));
 		   	   	  return;
 		   	   }
 		   }else{
 		   	   divy=abs_x_off/abs_y_off;
 		   	   if(abs_y_off>i16){
 		   	   	    
 	   	   	  	 	while(abs_y_off>i0){
 	   	   	  	 		if(abs_y_off>i16){
 	   	   	  	 			yy=i16;
 	   	   	  	 		}else{
 	   	   	  	 			yy=abs_y_off;
 	   	   	  	 		}
 	   	   	  	 		abs_y_off-=yy;
 	   	   	  	 		xx=yy*divy;
 	   	   	  	 		//abs_x_off-=xx;
 	   	   	  	 		  hadCrash=moveLogic(xx,yy);	
 	   	   	  	 		if(hadCrash)return; 
 	   	   	  	 	}
 		   	   }else{
 		   	   	  moveLogic(Math.abs(x_off),Math.abs(y_off));
 		   	   }	  
 		   }

		}
		private var x0,x1:Number;
		private var y0,y1:Number;
		private var crash_x:Boolean;
		private var crash_y:Boolean;
		private function moveLogic(xx:Number,yy:Number):Boolean{
 	 		x0=xx*x_flg;
 	 		y0=yy*y_flg;
 	 		crash_x=actorMoveInPhyLayerX(x0,y0);
 	 	
 	 		crash_y=actorMoveInPhyLayerY(x0,y0);
 	 	
            //检测碰撞发生
 	 		if(crash_x||crash_y){
                if(x_crash_length>i1 && y_crash_length>i1){//x,y方向都有tile越界
                	crashActionXY();
                }else if(x_crash_length==i0 || y_crash_length>i1){//只有x方向有tile越界，发生了碰撞
                	crashActionY(xx,yy);
                }else if(y_crash_length==i0 || x_crash_length>i1){//只有y方向有tile越界，发生了碰撞
                    crashActionX(xx,yy);
                }else{//角碰撞
                	crashActionXY();
                }
                //trace(car._x+"  crash  "+car._y+"   "+y_crash_length+"  "+x_crash_length);
                return retb=true;
 	        }
 	        car._x+=xx*x_flg;
	        car._y+=yy*y_flg; 
	       // trace(car._x+"     "+car._y);
 	 		return retb=false;
		}
		//双边发生碰撞 或者 角碰撞
		var number,number1:Number;
		private function crashActionXY():void{
//			 trace("X  Y");
 			 car._x=x1;
 			 car._y=y1; 
	     	 car.sideClipContrl.addCrash(number=car._vx*i_1/d1d5,number1=car._vy*i_1/d1d5);  

		}
		//单边碰撞
		private function crashActionX(xx:Number,yy:Number):void{
//           trace(car._x+" xxx crash  "+x1*x_flg +"   "+x_crash_length+"  "+y_crash_length);
	      	  car._x=x1;
	 	 	  car._y+=yy*y_flg;  
	 	  
	 	     car.sideClipContrl.addCrash(number=car._vx*i_1/d1d5,number1=car._vy/d1d5);   
		}
		
		private function crashActionY(xx:Number,yy:Number):void{
// 	   trace(car._y+" YYY crash  "+y1*y_flg +"   "+y_crash_length+"  "+x_crash_length);
	            car._x+=xx*x_flg; 
	     	 	car._y=y1; 
	     	 	car.sideClipContrl.addCrash(number=car._vx/d1d5,number1=car._vy*i_1/d1d5); 
	     	 	 
		}
		
		private var x_crash_length:int;
		private var y_crash_length:int;
		private var x_block:int;
		private var start_y_block:int;
		private var end_y_block:int;
		private function actorMoveInPhyLayerX(x_off:Number,y_off:Number):Boolean{
             x=car._x+x_off;
             y=car._y+y_off;
		     left_x=x-half;
		     right_x=x+half;
		     up_y=y-half;
		     down_y=y+half;
		      
		     x_crash_length=i0;
		     x1=x;
	         
		       switch (x_dir) {
   				  case DEF.DIRECTION_LEFT:
	               x_block= Math.floor(number=left_x/i16);
		           
		           var o_x_block:int=Math.floor(number=(car._x-half)/i16);
		           if(x_block<i0)return retb=false;
		           if(o_x_block==x_block)return retb=false;
		           
		           start_y_block=Math.floor(number= up_y/i16);
		           end_y_block=Math.floor(number= down_y/i16);
		            if((number=down_y%i16)==i0){
	            		end_y_block--;
	                }
	                  if(start_y_block<i0)start_y_block=i0;
		        	if(end_y_block>=mapInfo.height_in_tiles)end_y_block=mapInfo.height_in_tiles-i1;
		              for(y_y=start_y_block;y_y<=end_y_block;y_y++){
		               intTemp=y_y*mapInfo.width_in_tiles+x_block;
		               if(!pointCanPass(intTemp)){
		               ///	trace("x_block "+x_block)
		               	  x_crash_length++;	
		           	               	
		                } 
		             }
		             if(x_crash_length>i0){
		             	x1=x_block*i16+i16+half;
		             	return retb=true;
		             }
		           break;
		         case DEF.DIRECTION_RIGHT:
                
	            x_block= Math.floor(number=right_x/i16);
	             o_x_block=Math.floor(number=(car._x+half)/i16);
	            if((number=(car._x+half)%i16)==i0){
	            	o_x_block--;
	            }
	            if((number=right_x%i16)==i0){
	            	x_block--;
	            }
	            //trace("x1   "+x_off+"  "+(right_x%16));
	            //if(x1<0||x1>Math.abs(x_off))x1=Math.abs(x_off);
		           if(x_block>=mapInfo.width_in_tiles)return retb=false;
		            if(o_x_block==x_block)return retb=false;
		            
		           start_y_block=Math.floor( number=up_y/i16);
		           end_y_block=Math.floor(number= down_y/i16);
			        if((number=down_y%i16)==i0){
	            		end_y_block--;
	                }
	                if(start_y_block<i0)start_y_block=i0;
			       if(end_y_block>=mapInfo.height_in_tiles)end_y_block=mapInfo.height_in_tiles-i1;
		             for( y_y=start_y_block;y_y<=end_y_block;y_y++){
		               intTemp=y_y*mapInfo.width_in_tiles+x_block;
		               if(!pointCanPass(intTemp)){
		                  x_crash_length++;
		                  //trace("x1   "+x_off+"  "+(right_x%16));
		                } 
		               
		             }
		             if(x_crash_length>i0){
		             	x1=x_block*i16-half;
		             	return retb=true;
		             }
		           break;
		       }
			return retb=false;	
		}
		private var start_x_block,end_x_block:int;
		private var half,left_x,right_x,up_y,down_y,kk:Number;
		private var x_dir,y_dir,y_block,x_x,y_y:int;
		private var intTemp:Number=i0;
		private var x,y:Number;
     public  function actorMoveInPhyLayerY(x_off:Number,y_off:Number):Boolean {  //  =i0 conflict, >i0 not conflict  ,<i0 in can not pass zone
             x=car._x+x_off;
             y=car._y+y_off;
      		 left_x=x-half;
       right_x=x+half;
       up_y=y-half;
       down_y=y+half;

           
		y_crash_length=i0;
		y1=y;
       switch (y_dir) {
         case DEF.DIRECTION_UP:
             y_block= Math.floor(number=up_y/i16);
            var o_y_block:int=Math.floor(number=(car._y-half)/i16);
		           
         if(y_block<i0)return retb=false;
         if(o_y_block==y_block)return retb=false;
           start_x_block=Math.floor(number=left_x/i16);
          
           end_x_block=Math.floor(number=right_x/i16);
	            if((number=right_x%i16)==i0){
	            	end_x_block--;
	            }
	        if(start_x_block<i0)start_x_block=i0;
			if(end_x_block>=mapInfo.width_in_tiles)end_x_block=mapInfo.width_in_tiles-i1;
             for(x_x=start_x_block;x_x<=end_x_block;x_x++){
               intTemp=y_block*mapInfo.width_in_tiles+x_x;
               if(!pointCanPass(intTemp)){
               	   y_crash_length++;
               }
             }
		             if(y_crash_length>i0){
		             	y1=y_block*i16+i16+half;
		             	return retb=true;
		             }
           break;
         case DEF.DIRECTION_DOWN:
	            y_block= Math.floor(number=down_y/i16);
	            o_y_block=Math.floor(number=(car._y+half)/i16);
	            if((number=(car._y+half)%i16)==i0){
	            	o_y_block--;
	            }
	            if((number=down_y%i16)==i0){
	            	y_block--;
	            }
	            //if(y1<0||y1>Math.abs(y_off))y1=Math.abs(y_off);
           if(y_block>=mapInfo.height_in_tiles)return retb=false;
            if(o_y_block==y_block)return retb=false;
            
           start_x_block =Math.floor(number=left_x/i16);
            end_x_block=Math.floor(number=right_x/i16);
            if((number=right_x%i16)==i0){
	            	end_x_block--;
	            }
 			if(start_x_block<i0)start_x_block=i0;
			if(end_x_block>=mapInfo.width_in_tiles)end_x_block=mapInfo.width_in_tiles-i1;
              for( x_x=start_x_block;x_x<=end_x_block;x_x++){
                 intTemp=y_block*mapInfo.width_in_tiles+x_x;
                 if(!pointCanPass(intTemp)) {
                 	
                 	y_crash_length++;
                 }
              }
		             if(y_crash_length>i0){
		             	y1=y_block*i16-half;
		             	return retb=true;
		             }
           break;

       }

       return retb=false;
     }
     private var retb:Boolean=false;
    private  function pointCanPass(i:int):Boolean{
     	  switch(mapInfo.physIdx[i]){
        		    	case DEF.TILE_TYPE_BUILDING:
        		    	//case DEF.TILE_TYPE_NOTPASS:
        		    	    //trace("no pass");
        		    	return retb=false;
        		    	default:
        		    	return retb=true;
           }
           return true;
     }
 

	}
}